#include "stdafx.h"
#include "detail/bmock_strict_mocks.hpp"

namespace bmock {
	void strict_mocks::add_expectation(exp_ptr new_exp) {
		push_back(new_exp);
	}

	void strict_mocks::expect_call_times_range(int min_, int max_) {
		back()->expect_call_times_range(min_, max_); 
	}

	void strict_mocks::not_received() {
		if (!back()->done_minimum_calls()) {
			back()->not_received();
		}
	}

	void strict_mocks::expect_call(const func_spec& f, const location& loc) {
		back()->expect_call(f, loc);
	}

	void strict_mocks::expect_arguments(const arg_list& args) {
		back()->expect_arguments(args);
	}

	exp_ptr strict_mocks::get_latest() const {
		return back();
	}

	void strict_mocks::set_result(const result_ptr& ptr) {
		back()->set_result(ptr);
	}

	std::pair<exp_ptr,boost::logic::tribool> strict_mocks::check(const func_spec& f, const arg_list& args) {
		if (empty()) {
			throw std::exception();
		}

		boost::logic::tribool tbool = false;

		exp_ptr p_e = front();	
		try {
			p_e->check_func(f);		//check if 'f' is the actual next call
			tbool = boost::logic::indeterminate;	//found the correct 'f', maybe args wrong. indeterminate-so that stub will not overwrite
			p_e->check_args_no_msg(args);
		}
		catch (...) {
			if (p_e->done_minimum_calls()) {
				pop_last();
				return check(f, args);
			}
			return std::make_pair(p_e, tbool);
		}

		return std::make_pair(p_e, true);
	}

	bool strict_mocks::is_done() const {	
		for (std::list<exp_ptr>::const_iterator it = begin(); it != end(); ++it) {
			if (!(*it)->done_minimum_calls()) {
				return false;
			}
		}

		return true;
	}

	bool strict_mocks::empty() const {
		return std::list<exp_ptr>::empty();
	}

	void strict_mocks::pop_last() {
		pop_front();
	}
}